package com.bear.pk.handler;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bear.pk.entity.Roles;
import com.bear.pk.entity.UserRoles;
import com.bear.pk.entity.Users;
import com.bear.pk.exception.ResourceNotFoundException;
import com.bear.pk.service.IRolesService;
import com.bear.pk.service.IUserRolesService;
import com.bear.pk.service.IUsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    IUsersService userService;

    @Autowired
    IUserRolesService userRolesService;

    @Autowired
    private IRolesService rolesService;

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String usernameOrEmail)
            throws UsernameNotFoundException {
        // Let people login with either username or email
        Users users = Optional.ofNullable(userService.getOne(Wrappers.<Users>lambdaQuery().eq(Users::getUsername, usernameOrEmail)))
                .orElseThrow(() ->
                        new UsernameNotFoundException("User not found with username or email : " + usernameOrEmail)
        );
        List<UserRoles> userRolesList = userRolesService.list(Wrappers.<UserRoles>lambdaQuery().eq(UserRoles::getUserId, users.getId()));
        List<Long> roleIdList = userRolesList.stream().map(UserRoles::getRoleId).collect(Collectors.toList());
        List<Roles> roles = rolesService.listByIds(roleIdList);
        users.setRoles(roles);
        return UserPrincipal.create(users);
    }

    @Transactional
    public UserDetails loadUserById(Long id) {
        Users users = Optional.ofNullable(userService.getById(id)).orElseThrow(
            () -> new ResourceNotFoundException("User", "id", id)
        );
        List<UserRoles> userRolesList = userRolesService.list(Wrappers.<UserRoles>lambdaQuery().eq(UserRoles::getUserId, users.getId()));
        List<Long> roleIdList = userRolesList.stream().map(UserRoles::getRoleId).collect(Collectors.toList());
        List<Roles> roles = rolesService.listByIds(roleIdList);
        users.setRoles(roles);
        return UserPrincipal.create(users);
    }
}